home *** CD-ROM | disk | FTP | other *** search
/ IRIS Performer 2.2 Friends Demo / SGI IRIS Performer 2.2 Friends Demo.iso / friends / technology_playgroup / unwinder / driver_simple / read_dual.c < prev   
C/C++ Source or Header  |  1997-11-17  |  8KB  |  283 lines

  1. /**********************************************************************
  2.  * TECHNOLOGY PLAYGROUP INC.   http://this.is/tpg   email: tpg@this.is
  3.  **********************************************************************
  4.  *
  5.  * read_dual.c
  6.  *
  7.  * Version:  1.0 
  8.  * Date: 17 november 1997 
  9.  *
  10.  * Sample program to open the serial port, and poll data from the 
  11.  * UNWINDER dual joystick adapter v2.1.  
  12.  *
  13.  * This should get you started in writing a basic serial port driver,
  14.  * refer to the technical documentation for details on the data format,
  15.  * protocols, etc.  This program only checks for a bad checksum, you
  16.  * should also be checking the Status and Mode byte bits.
  17.  *
  18.  *
  19.  **********************************************************************/
  20.  
  21.  
  22. /**********************************************************
  23.  * New machines such as O2/Origin/Octane use a new termios
  24.  * data structure for IRIX 6.xx to support baud rates     
  25.  * above 38400.                                           
  26.  * To use the old termios - uncomment the next line    
  27.  *********************************************************/
  28. /* #define OLD_TERMIO */
  29.  
  30.  
  31. #include <stdio.h>   /* Standard input/output definitions */
  32. #include <string.h>  /* String function definitions */
  33. #include <unistd.h>  /* UNIX standard function definitions */
  34. #include <fcntl.h>   /* File control definitions */
  35. #include <errno.h>   /* Error number definitions */
  36. #include <termios.h> /* POSIX terminal control definitions */
  37.  
  38.  
  39. const char* serial_port = "/dev/ttyd2";
  40.  
  41.  
  42. /*************************************
  43.  *       single joystick mode
  44.  *************************************/
  45. /* const char* poll_cmd = "1";       */
  46. /* int num_bytes = 11;               */
  47.  
  48.  
  49. /*************************************
  50.  *        dual joystick mode
  51.  *************************************/
  52. const char* poll_cmd = "3";   /* command to poll data          */ 
  53. int num_bytes = 19;           /* number of bytes from UNWINDER */
  54.  
  55.  
  56. int fd;
  57. char in[1000];
  58. char buffer[1000];
  59.  
  60. struct termio termio;
  61.  
  62.  
  63. /********************************
  64.  *  joystick data structure
  65.  *******************************/
  66. typedef struct {
  67.   unsigned short x;        /* X stick axis (left/down)              */
  68.   unsigned short y;        /* Y stick axis (up/down)                */
  69.   unsigned short z;        /* Z stick axis (rotation)               */
  70.   unsigned short t;        /* T stick axis (slider)                 */
  71.   unsigned char buttons;   /* all buttons switch status             */
  72.   unsigned char hat;       /* hat position                          */
  73.   unsigned char sw;        /* switch on or off (digital mode only)  */
  74. } joystick;
  75.  
  76.  
  77.  
  78. /********************************
  79.  *  setup serial port termios
  80.  *******************************/
  81. open_port(void)
  82. {
  83.     fd = open(serial_port, O_RDWR, 0666 );
  84.     if (fd == -1)
  85.       {
  86.     printf("open %s - failed with error %s\n",serial_port,strerror(errno));
  87.     return 0;
  88.       }
  89.  
  90.     /* see man page for 'termio' -- for serial port setup */
  91.     ioctl(fd, TCGETA, &termio );
  92.     termio.c_iflag = 0;  
  93.     termio.c_oflag = 0;
  94.  
  95. #ifdef OLD_TERMIO
  96.     termio.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
  97. #else
  98.     termio.c_cflag = CS8 | CREAD | CLOCAL;
  99.     termio.c_ispeed = B9600;
  100.     termio.c_ospeed = B9600;
  101. #endif
  102.     termio.c_lflag = 0;
  103.     termio.c_line = 0;
  104.     termio.c_cc[0] = 0;
  105.     termio.c_cc[VMIN] = 0;    /* non-blocking mode */
  106.     termio.c_cc[VTIME] = 1;   /* .1 sec timeout    */
  107.     ioctl(fd, TCSETA, &termio);
  108.  
  109.    return (fd);
  110. }
  111.  
  112.  
  113. /********************************
  114.  *  CONVERT raw joystick data 
  115.  *******************************/
  116. void ProcessData(char* data, joystick* joy)
  117. {
  118.  
  119.   /* Data format as follows:
  120.                        BITS
  121.     BYTE -7---6--5--4--3--2--1--0-  DESCRIPTION
  122.     0    X11 X10 X9 X8 X7 X6 X5 X4  X-axis most significant bits
  123.     1    Y11 Y10 Y9 Y8 Y7 Y6 Y5 Y4  Y-axis most significant bits
  124.     2    Z11 Z10 Z9 Z8 Z7 Z6 Z5 Z4  Z-axis most significant bits
  125.     3    T11 T10 T9 T8 T7 T6 T5 T4  T-axis most significant bits
  126.     4     X3  X2 X1 X0 Y3 Y2 Y1 Y0  X-axis LSB, Y-axis LSB
  127.     5     Z3  Z2 Z1 Z0 T3 T2 T1 T0  Z-axis LSB, T-axis LSB
  128.     6     B7  B6 B5 B4 B3 B2 B1 B0  buttons
  129.     7     --  -- -- CH H3 H2 H1 H0  CH=switch (digital only) / hat
  130.     
  131.   */
  132.  
  133.   /* upper 8 bits are combined with lower 4 bits to get a 12-bit value */
  134.   joy->x = (data[0] << 4) | ((data[4]&0xF0) >> 4);
  135.   joy->y = (data[1] << 4) |  (data[4]&0x0F);
  136.   joy->z = (data[2] << 4) | ((data[5]&0xF0) >> 4);
  137.   joy->t = (data[3] << 4) |  (data[5]&0x0F);
  138.   
  139.   joy->buttons = data[6];
  140.  
  141.   /* lower 4 bits only - hat - digital mode only */
  142.   joy->hat     = data[7]&0x0F;
  143.  
  144.   /* switch on Sidewinder3D Pro - digital mode only */
  145.   joy->sw      = (data[7]>>4) & 01;
  146.  
  147. }
  148.  
  149.  
  150. /********************************
  151.  *    OUTPUT bits as binary 
  152.  *******************************/
  153. void output_binary(char x)   
  154. {
  155.   int b;
  156.   for (b=7; b>=0; b--) {
  157.     printf("%1d", ((x>>b) &01));
  158.   }
  159.   printf(" ");
  160. }
  161.  
  162.  
  163. /********************************
  164.  *     OUTPUT joystick data 
  165.  *******************************/
  166. void PrintJoy(joystick* joy)
  167. {
  168.   int i;
  169.   printf("x:%4u y:%4u z:%4u t:%4u hat:%2u sw:%1u but:", 
  170.          joy->x,  joy->y, joy->z, joy->t, joy->hat, joy->sw);
  171.   output_binary(joy->buttons);  
  172. }
  173.  
  174.  
  175.  
  176. /********************************
  177.  *     MAIN program loop 
  178.  *******************************/
  179. main(int argc, char **argv)
  180. {
  181.     int i,n;
  182.     char checksum;
  183.     joystick joy1;
  184.     joystick joy2;
  185.  
  186.  
  187.     printf("Opening serial port: %s. \n", serial_port);  
  188.     open_port();
  189.  
  190.     n=write(fd,"p",1);
  191.     printf("Polled mode\n");
  192.     if (n<1) {
  193.       printf("ERROR:  write returned  %d\n", n);
  194.       exit(1);
  195.     }
  196.  
  197.  
  198.     /* Buffer is cleared because by UNWINDER wakes up in continous mode */
  199.     printf("Clearing buffer: [");
  200.     do {
  201.       n=read(fd,buffer,1);
  202.       printf("%s",buffer);
  203.     } while (n>0);
  204.     printf("]\n");
  205.  
  206.  
  207.     /* You need a minimum 20 millisecond delay between each command sent */
  208.     sleep(1);
  209.     write(fd,"A",1);   /*  use 'a' for analog mode */
  210.     printf("joystick 1 - Digital Mode\n");
  211.     sleep(1);
  212.     write(fd,"b",1);   /*  use 'B' for digital mode */
  213.     printf("joystick 2 - Analog Mode\n");
  214.     sleep(1);
  215.     write(fd,"X",1);  
  216.     printf("on-change mode OFF\n");
  217.     sleep(1);
  218.     write(fd,"n",1); 
  219.     printf("debug mode OFF\n");
  220.     sleep(1);
  221.     write(fd,"v",1);  /* output UNWINDER version */
  222.     do { 
  223.       n=read(fd,buffer,1);
  224.       printf("%s",buffer);
  225.     } while (n>0);
  226.   
  227.  
  228.     /* SETUP POLLING MODE  block for the length of the packet */
  229.     ioctl(fd, TCGETA, &termio );
  230.     termio.c_cc[VMIN] = num_bytes;    /* set number of characters in packet */
  231.     termio.c_cc[VTIME] = 0;           /* set to blocking mode               */
  232.     ioctl(fd, TCSETA, &termio);
  233.  
  234.     printf("\nSerial port blocking for %d characters\n\n",num_bytes);
  235.  
  236.     /* INFINITE LOOP */
  237.     while (1) {
  238.       n=write(fd,poll_cmd,1);   /* poll UNWINDER */
  239.       if (n<1) {
  240.     printf("Error sending poll command - write returned %d\n",n);
  241.     exit(1);
  242.       }
  243.       
  244.       n=read(fd,in,num_bytes);  /* read data from UNWINDER */
  245.       if (n!=num_bytes) { 
  246.     printf("Error reading data - read returned %d\n", n); }
  247.       else {
  248.  
  249.     printf("status ");
  250.     output_binary(in[0]);
  251.     printf("mode ");
  252.     output_binary(in[1]);
  253.  
  254.     ProcessData(in+2, &joy1); /* process data starting at byte 3 */
  255.     PrintJoy(&joy1);
  256.     ProcessData(in+10,&joy2); /* process data starting at byte 11 */
  257.     PrintJoy(&joy2);
  258.  
  259.     checksum=0; /* calculate checksum */
  260.         for(i = 0; i < (num_bytes-1); i++) { checksum = checksum+in[i]; }
  261.     if (checksum==in[i]) { printf("%3d OK\n",checksum); } else {
  262.       printf("%3d ERROR CHECKSUM=%3d\n",in[i],checksum); 
  263.     }
  264.       }
  265.     }
  266.  
  267. }
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.